package com.qm.console.pubdef.dto.bx;

import com.alibaba.fastjson.JSON;
import com.qm.console.component.exception.BusinessException;
import com.qm.console.controller.dto.ResultEnum;
import com.qm.console.dao.mapper.BxAtomFieldDOMapper;
import com.qm.console.dao.mapper.BxDisplayFieldDOMapper;
import com.qm.console.dao.model.BxAtomFieldDO;
import com.qm.console.dao.model.BxAtomFieldDOExample;
import com.qm.console.dao.model.BxDisplayFieldDO;
import com.qm.console.dao.model.BxDisplayFieldDOExample;
import com.qm.console.dao.model.BxJobDO;
import com.qm.console.pubdef.constant.bx.BxGroupers;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import lombok.Getter;
import lombok.Setter;

/**
 * //                       _oo0oo_
 * //                      o8888888o
 * //                      88" . "88
 * //                      (| -_- |)
 * //                      0\  =  /0
 * //                    ___/`---'\___
 * //                  .' \\|     |// '.
 * //                 / \\|||  :  |||// \
 * //                / _||||| -:- |||||- \
 * //               |   | \\\  -  /// |   |
 * //               | \_|  ''\---/''  |_/ |
 * //               \  .-\__  '-'  ___/-. /
 * //             ___'. .'  /--.--\  `. .'___
 * //          ."" '<  `.___\_<|>_/___.' >' "".
 * //         | | :  `- \`.;`\ _ /`;.`/ - ` : | |
 * //         \  \ `_.   \_ __\ /__ _/   .-` /  /
 * //     =====`-.____`.___ \_____/___.-`___.-'=====
 * //                       `=---='
 * //
 * //
 * //     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 * //
 * //               佛祖保佑         永无BUG
 * <p>
 * com.qm.console.pubdef.dto.bx
 * Created on 2021/1/8.
 */
@Getter
@Setter
public class BxJobDTO {

    private Integer id;
    private String jobName;
    private Integer type;
    private Integer state;
    private List<String> groupers;
    private List<BxDisplayFieldDTO> displayFields;
    private Date createTime;
    private Date updateTime;
    private Date lastFinishTime;
    private String lastFailedReason;

    public static BxJobDTO fromDO(BxJobDO src, BxDisplayFieldDOMapper displayFieldDOMapper, BxAtomFieldDOMapper atomFieldDOMapper) {
        BxJobDTO result = new BxJobDTO();
        BeanUtils.copyProperties(src, result);
        result.setGroupers(src.getGroupers() != null ? Arrays.stream(src.getGroupers().split(",")).collect(Collectors.toList()) : Collections.emptyList());
        if (!StringUtils.isEmpty(src.getDisplayFields())) {
            result.setDisplayFields(parseDisplayFields(src.getDisplayFields(), displayFieldDOMapper, atomFieldDOMapper));
        }

        return result;
    }

    public static List<BxDisplayFieldDTO> parseDisplayFields(String displayFields, BxDisplayFieldDOMapper displayFieldDOMapper, BxAtomFieldDOMapper atomFieldDOMapper) {
        List<Integer> ids = Arrays.stream(displayFields.split(",")).map(Integer::parseInt).collect(Collectors.toList());
        final BxDisplayFieldDOExample example = new BxDisplayFieldDOExample();
        example.createCriteria().andIdIn(ids);
        return displayFieldDOMapper.selectByExample(example).stream().map(item -> BxDisplayFieldDTO.fromDO(item, atomFieldDOMapper)).collect(Collectors.toList());
    }

    public BxJobDO toDO() {
        BxJobDO result = new BxJobDO();
        BeanUtils.copyProperties(this, result);
        result.setGroupers(groupers == null ? "" : String.join(",", groupers));
        result.setDisplayFields(displayFields == null ? "" : displayFields.stream().map(BxDisplayFieldDTO::getId).map(String::valueOf).collect(Collectors.joining(",")));
        return result;
    }

    public void validate(BxAtomFieldDOMapper atomFieldDOMapper, BxDisplayFieldDOMapper displayFieldDOMapper) {
        // validate grouper
        if (groupers != null) {
            if (!groupers.stream().allMatch(BxGroupers::isGrouper)) {
                throw new BusinessException(ResultEnum.BX_JOB_GROUPER_INVALIDATE);
            }
        }

        if (displayFields == null || displayFields.isEmpty()) {
            throw new BusinessException(ResultEnum.BX_JOB_DISPLAY_FIELD_INVALIDATE);
        } else {
            List<Integer> ids = displayFields.stream().map(BxDisplayFieldDTO::getId).collect(Collectors.toList());
            final BxDisplayFieldDOExample example = new BxDisplayFieldDOExample();
            example.createCriteria().andIdIn(ids);
            int count = displayFieldDOMapper.countByExample(example);
            if (count != ids.size()) {
                throw new BusinessException(ResultEnum.BX_JOB_DISPLAY_FIELD_INVALIDATE);
            }
        }
    }

}
